package com.wen.acl.service.impl;


import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wen.acl.entity.Permission;
import com.wen.acl.entity.RolePermission;
import com.wen.acl.entity.User;
import com.wen.acl.helper.MemuHelper;
import com.wen.acl.helper.PermissionHelper;
import com.wen.acl.mapper.PermissionMapper;
import com.wen.acl.service.PermissionService;
import com.wen.acl.service.RolePermissionService;
import com.wen.acl.service.UserService;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;

/**
 * <p>
 * 权限 服务实现类
 * </p>
 *
 * @author testjava
 * @since 2020-01-12
 */
@Service
public class PermissionServiceImpl extends ServiceImpl<PermissionMapper, Permission> implements PermissionService {

    @Resource
    private RolePermissionService rolePermissionService;

    @Resource
    private UserService userService;

    /**
     * 递归查询所有菜单
     *
     * @return 最终的菜单集合
     */
    @Override
    public List<Permission> queryAllMenu() {
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.orderByDesc("id");
        List<Permission> permissionList = baseMapper.selectList(wrapper);
//      通过递归构建菜单
        return buildPermission(permissionList);
    }

    /**
     * 根据角色查询所拥有的菜单
     *
     * @param roleId 角色id
     * @return 返回要查询的角色所拥有的菜单集合
     */
    @Override
    public List<Permission> selectAllMenuByRole(String roleId) {
        List<Permission> allPermissionList = baseMapper.selectList(new QueryWrapper<Permission>().orderByAsc("CAST(id AS SIGNED)"));
        //根据角色id获取角色权限
        List<RolePermission> rolePermissionList = rolePermissionService.list(new QueryWrapper<RolePermission>().eq("role_id", roleId));
        for (Permission permission : allPermissionList) {
            for (RolePermission rolePermission : rolePermissionList) {
                if (rolePermission.getPermissionId().equals(permission.getId())) {
                    permission.setSelect(true);
                }
            }
        }
        return buildPermission(allPermissionList);
    }

    /**
     * 把所有返回菜单list集合进行封装的方法
     *
     * @param permissionList 查询出来的所有的菜单集合
     * @return 按照要求封装好的集合
     */
    public static List<Permission> buildPermission(List<Permission> permissionList) {
        //创建list集合，用于数据最终封装
        List<Permission> finalNode = new ArrayList<>();
        //把所有菜单list集合遍历，得到顶层菜单 pid=0菜单，设置level是1
        for (Permission parentPermission : permissionList) {
            //得到顶层菜单 pid=0菜单
            if ("0".equals(parentPermission.getPid())) {
                //设置顶层菜单的level是1
                parentPermission.setLevel(1);
                //根据顶层菜单，向里面进行查询子菜单，封装到finalNode里面
                finalNode.add(selectChildren(parentPermission, permissionList));
            }
        }
        return finalNode;
    }

    /**
     * 查询当前菜单下的子菜单
     *
     * @param parentPermission 当前菜单节点
     * @param permissionList   所有的菜单节点
     * @return 包含了子菜单的菜单节点
     */
    private static Permission selectChildren(Permission parentPermission, List<Permission> permissionList) {
        //1 因为向一层菜单里面放二层菜单，二层里面还要放三层，把对象初始化
//        parentPermission.setChildren(new ArrayList<>());
        //2 遍历所有菜单list集合，进行判断比较，比较id和pid值是否相同
        for (Permission childPermission : permissionList) {
            //判断 id和pid值是否相同
            if (parentPermission.getId().equals(childPermission.getPid())) {
                //设置当前菜单的level（为当前菜单的父菜单level+1）
                int level = parentPermission.getLevel() + 1;
                childPermission.setLevel(level);
                //如果children为空，进行初始化操作
                if (parentPermission.getChildren() == null) {
                    parentPermission.setChildren(new ArrayList<>());
                }
                //把查询出来的子菜单放到父菜单里面
                parentPermission.getChildren().add(selectChildren(childPermission, permissionList));
            }
        }
        return parentPermission;
    }

    /**
     * 递归删除当前菜单（及其子菜单）
     *
     * @param id 当前菜单id
     */
    @Override
    public void removeChildById(String id) {
        //1 创建list集合，用于封装所有删除菜单id值
        List<String> idList = new ArrayList<>();
        //2 向idList集合设置删除菜单id
        this.selectPermissionChildById(id, idList);
        //把当前id封装到list里面
        idList.add(id);
        baseMapper.deleteBatchIds(idList);
    }

    /**
     * 根据当前菜单id，查询菜单里面子菜单id，封装到list集合
     *
     * @param id     要删除的当前菜单id
     * @param idList 当前菜单及其子菜单的id集合
     */
    private void selectPermissionChildById(String id, List<String> idList) {
        //查询菜单里面子菜单id
        QueryWrapper<Permission> wrapper = new QueryWrapper<>();
        wrapper.eq("pid", id);
        wrapper.select("id");
        List<Permission> childIdList = baseMapper.selectList(wrapper);
        //把childIdList里面菜单id值获取出来，封装idList里面，做递归查询
        childIdList.forEach(item -> {
            //封装idList里面
            idList.add(item.getId());
            //递归查询
            this.selectPermissionChildById(item.getId(), idList);
        });
    }

    /**
     * 给角色分配菜单
     *
     * @param roleId        当前要分配菜单的角色id
     * @param permissionIds 要分配的菜单id（数组形式）
     */
    @Override
    public void saveRolePermissionRelationShip(String roleId, String[] permissionIds) {
        //1 创建list集合，用于封装添加数据
        List<RolePermission> rolePermissionList = new ArrayList<>();
        //遍历所有菜单数组
        for (String permissionId : permissionIds) {
            //RolePermission对象
            RolePermission rolePermission = new RolePermission();
            rolePermission.setRoleId(roleId);
            rolePermission.setPermissionId(permissionId);
            //封装到list集合
            rolePermissionList.add(rolePermission);
        }
        //添加到角色菜单关系表
        rolePermissionService.saveBatch(rolePermissionList);
    }

    /**
     * 根据用户id获取用户菜单
     *
     * @param id 用户id
     * @return 当前用户所拥有的菜单项
     */
    @Override
    public List<String> selectPermissionValueByUserId(String id) {

        List<String> selectPermissionValueList;
        if (this.isSysAdmin(id)) {
            //如果是系统管理员，获取所有权限
            selectPermissionValueList = baseMapper.selectAllPermissionValue();
        } else {
            selectPermissionValueList = baseMapper.selectPermissionValueByUserId(id);
        }
        return selectPermissionValueList;
    }

    @Override
    public List<JSONObject> selectPermissionByUserId(String userId) {
        List<Permission> selectPermissionList;
        if (this.isSysAdmin(userId)) {
            //如果是超级管理员，获取所有菜单
            selectPermissionList = baseMapper.selectList(null);
        } else {
            selectPermissionList = baseMapper.selectPermissionByUserId(userId);
        }

        List<Permission> permissionList = PermissionHelper.bulid(selectPermissionList);
        return MemuHelper.bulid(permissionList);
    }

    /**
     * 判断用户是否系统管理员
     *
     * @param userId 用户id
     * @return true or false
     */
    private boolean isSysAdmin(String userId) {
        User user = userService.getById(userId);
        return null != user && "admin".equals(user.getUsername());
    }
}
